package com.nais.controllers;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.util.StringUtils;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.nais.alipay.AlipayConfig;
import com.nais.alipay.AlipayService;
import com.nais.alipay.PagePayInfo;
import com.nais.constant.OrderStatus;
import com.nais.constant.OrderType;
import com.nais.domain.MainOrder;
import com.nais.mapper.MainOrderMapper;

@Controller
public class AlipayController {
	
	private final static Logger LOGGER = LoggerFactory.getLogger(AlipayController.class);

	@Autowired
	private MainOrderMapper mainOrderMapper;

	@PostMapping("/pay/alipay")
	public @ResponseBody String payByAliPay(String tradeNo)
	{
		String result = null;
		if (StringUtils.isEmptyOrWhitespace(tradeNo)) {
			LOGGER.warn("Have not post tradeNo to this page /pay/alipay");
			return null;
		}
		PagePayInfo payInfo = getPagePayInfo(tradeNo);
		AlipayService alipayService = AlipayService.getInstance();
		result = alipayService.pagePay(payInfo);
		return result;
	}
	
	@GetMapping("/pay/alipay/return")
	public String syncReturn(Model model, HttpServletRequest request) {
		
		Map<String,String> params = new HashMap<String,String>();
		Map<String,String[]> requestParams = request.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			//乱码解决，这段代码在出现乱码时使用
			try {
				valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			} catch (UnsupportedEncodingException e) {
				LOGGER.debug("", e);
			}
			params.put(name, valueStr);
		}
		
		boolean signVerified = checkSignature(params);
		
		String out_trade_no = request.getParameter("out_trade_no");
		String trade_no = request.getParameter("trade_no");
		String total_amount = request.getParameter("total_amount");

		//——请在这里编写您的程序（以下代码仅作参考）——
		if(signVerified) {
			try {
				out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
				trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
				total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
			} catch (UnsupportedEncodingException e) {
				LOGGER.debug("", e);
			}
		}else {
			// TODO return 404 or other page
			return null;
		}
		LOGGER.info("out_trade_no:{}, trade_no:{}, total_amount{}", out_trade_no, trade_no, total_amount);
		//model.addAttribute(arg0, arg1)
		return "pay-success";
	}
	
	@PostMapping("/pay/alipay/notify")
	public @ResponseBody String notify(HttpServletRequest request) {

		LOGGER.info("receive notify request");
		Map<String,String> params = new HashMap<String,String>();
		Map<String,String[]> requestParams = request.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			//乱码解决，这段代码在出现乱码时使用
			try {
				valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			} catch (UnsupportedEncodingException e) {
				LOGGER.info("", e);
			}
			params.put(name, valueStr);
		}
		boolean signVerified = false;
		LOGGER.info("notify http params:{}", params);
		signVerified = checkSignature(params); 

		String out_trade_no = request.getParameter("out_trade_no");
		String trade_no = request.getParameter("trade_no");
		String trade_status = request.getParameter("trade_status");
		
		if(signVerified) {//验证成功
			try {
				LOGGER.info("notify success, out_trade_no:{}, trade_no:{}, trade_status:{}", out_trade_no, trade_no, trade_status);
				out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
				trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
				trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
			} catch (UnsupportedEncodingException e) {
				LOGGER.info("", e);
			}
			
			if(trade_status.equals("TRADE_FINISHED")){
				LOGGER.info("trade finished, paymentSeq {}, alipay_trade_no", out_trade_no, trade_no);
			}else if (trade_status.equals("TRADE_SUCCESS")){
				MainOrder mainOrder = mainOrderMapper.selectByPaymentSeq(out_trade_no);
				mainOrder.setOrderStatus(OrderStatus.PAYSUCESS.getIndex());
				mainOrderMapper.updateByPrimaryKeySelective(mainOrder);
			}
			
			return "success"; 
			
		}else {
			LOGGER.info("signVerified failed");
			return "fail";
		}
	}
	
	private PagePayInfo getPagePayInfo(String paymentSeq) {
		MainOrder mainOrder = mainOrderMapper.selectByPaymentSeq(paymentSeq);
		PagePayInfo pagePayInfo = new PagePayInfo();
		pagePayInfo.setOutTradeNo(mainOrder.getPaymentSeq());
		pagePayInfo.setTotalAmount(longToCashString(mainOrder.getTotalAmount()));
		pagePayInfo.setSubject(OrderType.getName(mainOrder.getOrderType()));
		// TODO trade description
		pagePayInfo.setBody("");
		return pagePayInfo;
	}
	
	private String longToCashString(Long cashLong) {
		LOGGER.info("amount is {}", cashLong);
		String cents = String.valueOf(cashLong % 100);
		String yuan = String.valueOf(cashLong/100);
		return yuan + "." + cents;
	}

	private boolean checkSignature(Map<String, String> params) {
		try {
			return AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
		} catch (AlipayApiException e) {
			LOGGER.info("", e);
			return false;
		}
	}
}
